﻿/*
 * SharedPtr.h
 * 	supported
 * 	Deleter
 * 		例えばCOMポインタ等特殊なポインタ等の解放処理を任意に指定可能です。
 * 	voidポインタ
 * 		void*が格納できます。
 * 	アップキャスト
 * 		アップキャストをサポートします。
 *
 * 	not supported
 * 	ダウンキャスト
 * 		ほとんど使わないのでサポートしません。
 * 	循環参照
 * 		機構が複雑になるのでweakポインタを実装しません。
 *
 *  Created on: 2012/02/26
 *      Author: naoki
 */

#ifndef INCLUDED_NTENGINE_SHAREDPTR_H
#define INCLUDED_NTENGINE_SHAREDPTR_H

namespace NTEngine {
class SharedPtrCountedBase {
public:
	SharedPtrCountedBase() : mCount( 1 ) { }
	virtual ~SharedPtrCountedBase() { }
	void refer(){ ++mCount; }
	void unref() { --mCount; }
	int count() const { return mCount; }
private:
	int mCount;
};
template< class T, class DeleterT > class SharedPtrCountedImpl : public SharedPtrCountedBase {
public:
	SharedPtrCountedImpl( T* ptr, DeleterT deleter ) : mPtr( ptr ) , mDeleter( deleter ) { }
	~SharedPtrCountedImpl() { mDeleter( mPtr ); mPtr = 0; }
private:
	T* mPtr;
	DeleterT mDeleter;
};
class SharedCount {
public:
	SharedCount() : mImpl( 0 ) { }
	template< class T, class DeleterT >
	SharedCount( T* ptr, DeleterT del ) {
		mImpl = ( ptr ) ? NEW SharedPtrCountedImpl< T, DeleterT >( ptr, del ) : 0;
	}
	~SharedCount();
	SharedCount( const SharedCount& );
	void operator=( const SharedCount& );
private:
	SharedPtrCountedBase* mImpl;
};
template< typename T > struct SharedPtrTraits;

/**
 * @brief 参照カウンタ式スマートポインタ
 */
template< class T > class SharedPtr {
public:
	typedef typename SharedPtrTraits< T >::Reference Reference;
	typedef typename SharedPtrTraits< T >::ConstReference ConstReference;
	template< class U > friend class SharedPtr;

	// constructors
	SharedPtr();
	template< class U > explicit SharedPtr( U* );
	template< class U, class DeleterU > SharedPtr( U*, DeleterU );
	template< class U > SharedPtr( const SharedPtr< U >& );

	// operators
	Reference operator*();
	ConstReference operator*() const;
	Reference operator[]( int );
	ConstReference operator[]( int ) const;
	T* operator->();
	const T* operator->() const;
	bool operator==( const SharedPtr< T >& ) const;
	bool operator!=( const SharedPtr< T >& ) const;
	bool operator<( const SharedPtr< T >& ) const;
	operator void*() const;
private:
	T* mPtr;
	SharedCount mCount;
};

/**
 * @brief 便利コンストラクタ
 */
class SharedPtrCreator {
public:
	/**
	 * シングルポインタ用
	 */
	template< class T >
	static SharedPtr< T > create( T* p );

	/**
	 * 配列用
	 */
	template< class T >
	static SharedPtr< T > createArray( T* p );
};

} // namespace NTEngine

// 本体
#include "NTEngine/Base/Impl/SharedPtrImpl.h"

#endif // INCLUDED_NTENGINE_SHAREDPTR_H
